package jflowmap.views.heatmap;

import java.awt.Color;
import java.awt.Shape;
import java.util.Collection;
import java.util.List;

import jflowmap.model.graph.Graph;
import jflowmap.model.graph.Node;
import jflowmap.model.ontology.Dimension;
import jflowmap.util.Lasso;
import jflowmap.util.piccolo.PNodes;

import com.google.common.collect.Lists;

import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.util.PBounds;

public class SourceLayer extends AbstractLayer {

	private final Graph graph;
	private final VisualHeatMap visualHeatMap;
	private final List<Sink> sinks = Lists.newLinkedList();
	private final Lasso lasso;
	
	private double maxWidth = 0;
	
	public SourceLayer(VisualHeatMap visualHeatMap, double relativeWidth) {
		super(relativeWidth);
		
		this.graph = visualHeatMap.getGraph();
		this.visualHeatMap = visualHeatMap;
				
		createSinks();
		
		this.lasso = new Lasso(getCamera(), Color.CYAN) {
			@Override
			public void selectionMade(Shape shape) {
				SourceLayer.this.visualHeatMap.getHeatMapLayer().getView().getSelection("standard")
				.empty("SOURCE");
				
				for (Sink sink: sinks) {
					if (shape.contains(sink.getGlobalBounds().getCenter2D())) {
						SourceLayer.this.visualHeatMap.getHeatMapLayer().getView().getSelection("standard")
						.select("SOURCE", sink.getNode().getDimension());
					}
				}

				
				SourceLayer.this.visualHeatMap.update();
				SourceLayer.this.visualHeatMap.fitChildrenInView();
			}
		};
		
		getCamera().addInputEventListener(lasso);
	}

	private void createSinks() {
		
		final List<Sink> unorderedSinks = Lists.newLinkedList();
		
		for (final Node source: graph.getSourceNodes()) {
			unorderedSinks.add(createSink(source));					
		}
		
		for (Sink sink: unorderedSinks) {
			sink.setMaxWidth(maxWidth);
			this.addChild(sink);
			this.sinks.add(sink);
		}
	}
	
	
	private Sink createSink(final Node source) {
		final Sink sink = new Sink(source, visualHeatMap);
		
		if (sink.getWidth() > maxWidth) {
			maxWidth = sink.getWidth();
		}
		
		sink.setBounds(sink.getFullBounds());
		sink.setPaint(Color.WHITE);
		
		sink.addInputEventListener(new PBasicInputEventHandler() {
			@Override
			public void mouseClicked(PInputEvent event) {
				if (event.getClickCount() == 1) {
					visualHeatMap.getHeatMapView().getView()
					.getSelection("standard").toggle("SOURCE", source.getDimension());
				}
				
				visualHeatMap.fitChildrenInView();
			}
		});
		
		return sink;
	}

	@Override
	protected void layoutChildren() {
		super.layoutChildren();
		
		double y = 0;
		for (Sink sink: sinks) {
			sink.setOffset(0, y);
			y += sink.getFullBoundsReference().getHeight() + 8;
		}
	}
	
	@Override
	public void fitChildrenInView() {
		this.setFullBoundsInvalid(true);
		final PBounds bounds = this.getFullBounds();
		bounds.x -= bounds.width / 2;
		bounds.width *= 2;
		
		fitInView(bounds);
	}
	
	@Override
	public void update() {
		for (Sink sink: this.sinks) {
			sink.update();
		}
		super.update();
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub
		
	}
}
